package com.p2p.Androidp2p;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

import android.os.Environment;
import android.os.Message;
import android.util.Log;

/**
 * Class that initiates a socket connection with a host
 * 
 * @author Santiago
 * 
 */
public class Clientp2p implements Runnable
{
    private int filesize = 0;
    // host and port address
    private int port = 0;;
    private String host = null;
    private Socket server = null;
    private File saveFile = null;
    public String filename = null;
    private String checksum = null;

    public double percentFinished = 0;


    /**
     * client constructor that sets all the vars that the connection will use
     * 
     * @param ip
     *            - host address
     * @param size
     *            - size of file
     * @param portNum
     *            - port number
     * @param name
     *            - file name
     */
    public Clientp2p(String ip, int size, int portNum, String name, String csum)
    {
	host = ip;
	filesize = size;
	filename = name;
	port = portNum;
	checksum = csum;
    }

    /**
     * run runs through the client steps
     */
    public void run()
    {
	clientInit();
	getFile(filename);
	close();
	Log.d("ANDROIDP2P C:run", "file finished downloading");
	Peer.update();
    }

    /**
     * initiates connection with the server (host)
     */
    private void clientInit()
    {
	try
	{
	    server = new Socket(host, port);
	    
	} catch (Exception e)
	{
	    Log.d("ANDROIDP2P C:clientInit", e.getMessage());
	    return;
	}
    }

    /**
     * starts the receiving end of the file transfer and writes it to the
     * filename given
     * 
     * @param filename
     *            - the filename that is being transferred
     */
    public void getFile(String filename)
    {
	// sends the filename for the file that the server will fetch
	sendFileName(filename);

	//chosen because we needed it less then 8k 
	int chunkSize = 5000;
	byte[] fileArray = new byte[chunkSize]; 

	InputStream input = null;
	FileOutputStream fileOut = null;
	BufferedOutputStream bufferOut = null;
	int bytesRead = 0;
	int current = 0;
	percentFinished = 0.0;


	// this checks to make sure that the file can get connected
	checkFileName();

	// setting up the necessary streams and then getting the output from server
	try
	{
	    input = server.getInputStream();
	    fileOut = new FileOutputStream(saveFile);
	    bufferOut = new BufferedOutputStream(fileOut);

	    // keep reading in bytes until there are none left
		do
		{
		    bytesRead = input.read(fileArray, 0, fileArray.length);
		    
		    if (bytesRead >= 0)
		    {
			bufferOut.write(fileArray, 0, bytesRead);
			
			//calculates the percentage of the file downloaded
			current += bytesRead;
			percentFinished = ((double)current/ (double)filesize)*100;
			
			Message theMessage = AndroidP2P.progressUpdater.obtainMessage(0);
			theMessage.obj = this;
			AndroidP2P.progressUpdater.sendMessage(theMessage);
			 
		    }
		} while(bytesRead > -1);
		
		Log.d("final", ""+filesize);
		Log.d("current", ""+current);
		//waiting to test this till later
		/*
		if(compareChecksum(saveFile.getPath()))
		{
		    saveFile.delete();
		}
		*/
		 bufferOut.flush();
		 fileOut.close();    
		 input.close();
		 bufferOut.close();
	    
	} 
	catch (Exception e)
	{
	    Log.d("ANDROIDP2P C:getFile", e.getMessage());
	    return;
	}
    }
    
    private boolean compareChecksum(String filePath)
    {
	
	//need to implement
	String csum = Database.calculateChecksum(filePath);
	if(csum.equals(checksum))
	{
	    return true;
	}
	return false;
    }



    /**
     * sends the filename to the server so it can check if it has the file
     * actually
     * 
     * @param filename
     *            - the name of the file in question
     */
    private void sendFileName(String filename)
    {
	try
	{
	    PrintWriter out = new PrintWriter(new BufferedWriter(
		    new OutputStreamWriter(server.getOutputStream())), true);
	    out.println(filename);

	} catch (Exception e)
	{
	    Log.d("ANDROIDP2P C:sendFile", e.getMessage());
	    return;
	}

    }

    /**
     * receives the check string to see if the file exists or not
     */
    private void checkFileName()
    {
	try
	{
	    BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
	    String message = in.readLine();
	    if (message.equalsIgnoreCase("error"))
	    {
		close();
		System.exit(0);
	    }
	} catch (Exception e)
	{
	    Log.d("ANDROIDP2P C:checkFile", e.getMessage());
	    return;
	}
	
	// setting up the variables used in the file process
	File temp = Environment.getExternalStorageDirectory();
	File root = new File(temp, "Shared");

	if (root.canWrite())
	{
	    saveFile = new File(root, filename);
	}
    }

    /**
     * closes connection between server and client
     */
    private void close()
    {

	try
	{
	    server.close();

	} catch (IOException e)
	{
	    Log.d("ANDROIDP2P C:close", e.getMessage());
	    System.exit(1);
	}
    }
}
